﻿using System;
using System.Collections.Generic;
using System.Text;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.IO;
using System.Reflection;
namespace _0512063_0512082
{
    ///
    /// Lớp phát sinh một namespace hoàn chỉnh, có cả hàm main
    /// 
    class NetCodeGenerator:CodeGenerator
    {
        private CodeDomProvider provider;
        public CodeDomProvider Provider
        {
            get { return provider; }
            set { provider = value; }
        }

        private CodeAnalyser analyser;
        public CodeAnalyser Analyser
        {
            get { return analyser; }
            set { analyser = value; }
        }
        public NetCodeGenerator(CodeMemberMethod method, CodeDomProvider pro):base(method)
        {
            provider = pro;
        }

        /// <summary>
        /// Phát sinh toàn bộ chương trình
        /// </summary>
        /// <returns></returns>
        public override object start()
        {
            //Initialize CodeDom Variables			
            StringBuilder sbCode = new StringBuilder();
            StringWriter sw = new StringWriter(sbCode);       
            
                ICodeGenerator genarator = Provider.CreateGenerator(sw);
                CodeCompileUnit ccu = new CodeCompileUnit();
                CodeGeneratorOptions options = new CodeGeneratorOptions();
                options.BlankLinesBetweenMembers = false;

                 //Tạo namespace
                CodeNamespace cnsCodeDom = new CodeNamespace(nspace);
                ccu.Namespaces.Add(cnsCodeDom);
                cnsCodeDom.Imports.Add(new CodeNamespaceImport("System"));
                cnsCodeDom.Imports.Add(new CodeNamespaceImport("System.IO"));
                // Khai báo class
                CodeTypeDeclaration ctd = new CodeTypeDeclaration();
	            ctd.IsClass = true;
                ctd.Name = getMethodName();
                ctd.TypeAttributes = TypeAttributes.Public;
                cnsCodeDom.Types.Add(ctd);
                // Khai báo constructor
                ctd.Members.Add(CodeAnalyser.getConstrutor());             

			    // Khai báo các biến thành phần 
                ctd.Members.AddRange(CodeAnalyser.getAllMemberFields(mainMethod));                      
                // Khai báo các properties
                ctd.Members.AddRange(CodeAnalyser.getAllProperties(mainMethod));              
                // Khai báo hàm nhập
                ctd.Members.Add(CodeAnalyser.getInputMethod(mainMethod, prefix_in));
                // Khai báo hàm xuất
                ctd.Members.Add(CodeAnalyser.getOutputMethod(mainMethod, prefix_out));
                // Khai báo hàm kiểm tra
                ctd.Members.Add(CodeAnalyser.getCheckFunction(mainMethod, prefix_check));
                // Khai báo hàm xử lý
                ctd.Members.Add(CodeAnalyser.getProcess(mainMethod, prefix_process));
                // Khai báo hàm main
                CodeEntryPointMethod main = (CodeEntryPointMethod)mainFunction();
                ctd.Members.Add(main);
                genarator.GenerateCodeFromCompileUnit(ccu, sw, options);

                return FormatCode(sbCode.ToString());
               // return sbCode.ToString();
        }

        public override object mainFunction()
        {
            CodeEntryPointMethod entrypoint = new CodeEntryPointMethod();
            
            // Khai bao bien
            entrypoint.Statements.Add(CodeAnalyser.DeclareVariable(mainMethod.Name, "obj"));
            // gọi hàm nhập
            entrypoint.Statements.Add(CodeAnalyser.InvokeOperation("obj",prefix_in));
            // gọi hàm kiểm tra
            CodeConditionStatement condition = new CodeConditionStatement();
            condition.Condition = CodeAnalyser.InvokeOperation("obj", prefix_check);
            // biểu thức đúng
            condition.TrueStatements.Add(CodeAnalyser.InvokeOperation("obj", prefix_process));
            condition.TrueStatements.Add(CodeAnalyser.InvokeOperation("obj", prefix_out));
            // biểu thức sai
            condition.FalseStatements.Add(CodeAnalyser.getInstruction(leakdata));            
            entrypoint.Statements.Add(condition);
            // dừng 
            entrypoint.Statements.Add(CodeAnalyser.pauseApplication());
            return entrypoint;
        }

    }
}
